from flask_restful import Resource
from comment.models.user import User    # 验证当前用户名是否已存在数据库（验证是否唯一）
from flask import current_app, request, g
import random, json

from comment.utils.shopping_redis import redis_client
from flask_restful.reqparse import RequestParser    # 请求参数验证的

from comment.utils import parser
# import comment.utils.parser

from comment.models import db

from comment.utils.limiter import limiter as lmt

from comment.utils.tokens_pyjwt import generate_tokens
from shopping.resources.user import constants
from flask_limiter.util import get_remote_address

from comment.utils.decorators import login_required
# 我们定义测试的资源类
class Shopping_User(Resource):
    """
    加上登录拦截
    """
    method_decorators = {   # 在get和post请求上加了登录拦截
        'get': [login_required],
        'post': [login_required],
    }
    def get(self):
        current_app.logger.info("我的测试日志")
        # 这里的代码可能会用到User模型类
        return {"hello": "测试"}

    def post(self):
        return {'hello': "post successful"}

    def put(self):
        return {"hello": 'put successful'}


class User_SMS(Resource):
    # 发送短信验证码
    error_message = "To many requests."
    decorators = [
        # 三个参数：参数1：限流的速率 参数二：必须是一个函数 参数三：超出限制之后的提示信息
        lmt.limit(constants.LIMIT_SMS_CODE_BY_MOBILE,key_func=lambda: request.args.get("phone"),error_message=error_message),# 一分钟只能发送一次
        lmt.limit(constants.LIMIT_SMS_CODE_BY_MOBILE,key_func=get_remote_address,error_message=error_message),  # 一个小时只能发送10次
    ]

    def get(self):
        phone = request.args.get("phone").split()
        code = random.randint(1000, 9999)
        result = send_sms(phone, str(code)) # 返回的json的字符串对象
        result = json.loads(result)  # 把json变成字典
        # 往result里面添加手机号码
        result["phone"] = phone

        # 短信验证码发送成功之后，还需要把验证码存放到redis数据库中，以便下次验证，验证码的失效为5分钟
        redis_client.setex("shopping:code:{}".format(phone), constants.SMS_CODE_EXPIRES, code)   # 参数1：key ，参数2：时效 ，参数3：value-->code

        return result


class AuthorizationCodeResource(Resource):
    # 提交手机号和验证码验证
    def post(self):
        rp = RequestParser()
        rp.add_argument("phone", type=parser.mobile, required=True)
        rp.add_argument("code", type=parser.regex(r"^\d{6}$"), required=True)
        args = rp.parse_args()
        phone = args.phone
        code = args.code

        #从redis数据库中得到之前保存的验证码
        key = "shopping:code:{}".format(phone)
        try:
            real_code = redis_client.get(key)   # 从redis中返回的是字节数据
        except ConnectionError as e:
            current_app.logger.error(e)
            return {"message": "redis db connect error."}, 400
        # 开始验证
        if not real_code or real_code.decode() != code: # 解码，因为是数字，所有任何编码格式都一样
            return {"message":"Invalid code."}, 400

        return {"phone": phone, "message": "code success."}


class RegisterUserResource(Resource):
    """
    填写账号信息，完成用户的注册
    """
    def post(self):
        rp = RequestParser()
        rp.add_argument("phone", type=parser.mobile, required=True)
        rp.add_argument("username", required=True)
        rp.add_argument("password", required=True)
        rp.add_argument("email", type=parser.email, required=True)
        args = rp.parse_args()
        phone = args.phone
        username = args.username
        password = args.password
        email = args.email

        # 验证用户名是否唯一：先从mysql数据库中根据当前用户名查询
        u = User.query.filter(User.username == username).first()
        if u:   # 为真表示用户名已经存在
            current_app.logger.info("{} : 用户名已经存在，请换一个".format(username))
            return {"message": "The username already exists."}, 400

        # 把用户名信息保存到数据库中
        u = User(username=username, pwd=password, email=email, status=0)
        db.session.add(u)
        db.session.commit()
        return {'message': "ok"}


class UserLoginResource(Resource):
    # 登录
    def post(self):
        username = request.form.get("username")
        password = request.form.get('password')

        if not all([username, password]):
            return {"message": "数据不完整"}, 401
        user = User.query.filter(User.username == username).first()
        if user:
            if user.check_password(password):
                # 必须把登录之后的用户 id得到token，token返回给前端
                token = generate_tokens(user.id)
                return {"msg": "Login Success", "token": token, 'username': username}, 200
        return {"message": "用户名或者密码错误"}, 400


class UserLoginOutResource(Resource):
    """
    退出登录
    """
    def post(self):
        if g.user_id:
            g.user_id = None
        return {'message': '退出登录成功'}


class IsExistPhoneResource(Resource):
    """
    判断手机号是否存在
    """
    def post(self):
        phone = request.form.get('phone')
        user = User.query.filter(User.phone==phone).first()
        if user:
            return {'isExist': True, 'message': '此手机号码已经注册', 'code': 203}
        return {'message': '手机号可以注册'}